#include <cexpert.h>
#include <DBChecker.h>
#include <Driver.h>
#include "init_drivers.hpp"

#include <mysql/mysql.h>

#include <cassert>
#include <iostream>

void* checker_thread(void* arg){
    CExpert::DBChecker* self = reinterpret_cast<CExpert::DBChecker*>(arg);
    const CExpert::DBChecker::conn_params& cp = self->get_cp();

    while (!self->is_stopped()){
        try{
            if (!CExpert::get_driver(cp.driver)(cp)){
                self->fail();
            } else{
                self->ok();
            }
        }
        catch (const std::exception& ex){
            std::cerr << ex.what() << std::endl;
            self->stop();
        }
        sleep(1);
    }
    return NULL;
}

void check(const char* conn_str, bool result){
    std::cout << "checking " << conn_str << std::endl;
    CExpert::DBChecker c2(conn_str, true); c2.start(&checker_thread);
    cexpert_get_is_available(conn_str);
    sleep(10);
    std::cout << "\tinitiated, check now" << std::endl;
    assert(cexpert_get_is_available(conn_str) == result);
    std::cout << "ok (" << (result?std::string("available"):std::string("not available")) << ")" << std::endl;
}



int main(){
	std::cout << "start client test" << std::endl;
    check("http://img.yandex.net:80/i/www/logo.png", true);
    check("http://www.yandex.ru", true);
    check("http://www.yandex.ru:81/ping", false);

    {
        const char* fail = "mysql://user:passwd@nosuchhostaacccca:7778/nosuchdb";
        std::cout << "checking " << fail << std::endl;

        CExpert::DBChecker c1(fail, true); c1.start(&checker_thread);
        //CExpert::DBChecker c2(ok, true); c2.start();

        cexpert_get_is_available(fail);
        //cexpert_get_is_available(ok);
        sleep(10);
        std::cout << "\tinitiated, check now" << std::endl;
        assert(cexpert_get_is_available(fail) == false);
        std::cout << "ok" << std::endl;
        //std::cout << "checking ok conn" << std::endl;
        //assert(cexpert_get_is_available(ok) == true);
    }
    {
        std::cout << "checking tcp://yandex.ru:80" << std::endl;
        const char* tcp_check = "tcp://yandex.ru:80";
        CExpert::DBChecker c2(tcp_check, true); c2.start(&checker_thread);
        cexpert_get_is_available(tcp_check);
        sleep(10);
        std::cout << "\tinitiated, check now" << std::endl;
        assert(cexpert_get_is_available(tcp_check) == true);
        std::cout << "ok" << std::endl;
    }
    {
        std::cout << "checking tcp://yandex.ru:81" << std::endl;
        const char* tcp_check = "tcp://yandex.ru:81";
        CExpert::DBChecker c2(tcp_check, true); c2.start(&checker_thread);
        cexpert_get_is_available(tcp_check);
        sleep(10);
        std::cout << "\tinitiated, check now" << std::endl;
        assert(cexpert_get_is_available(tcp_check) == false);
        std::cout << "ok" << std::endl;
    }

    {
        const char* check = "mongo://linda.dev.yandex.net:27017/anything";
        std::cout << "checking " << check << std::endl;
        CExpert::DBChecker c2(check, true); c2.start(&checker_thread);
        cexpert_get_is_available(check);
        sleep(10);
        std::cout << "\tinitiated, check now" << std::endl;
        assert(cexpert_get_is_available(check) == true);
        std::cout << "ok" << std::endl;
    }
    {
        const char* check = "mongo://linda.dev.yandex.net/anything";
        std::cout << "checking " << check << std::endl;
        CExpert::DBChecker c2(check, true); c2.start(&checker_thread);
        cexpert_get_is_available(check);
        sleep(10);
        std::cout << "\tinitiated, check now" << std::endl;
        assert(cexpert_get_is_available(check) == true);
        std::cout << "ok" << std::endl;
    }
    check("mongo://yandex.net:27017/anything", false);

	const char* register_test_cstr = "mysql://user:passwd@nosuchhostaacccca:7778/register_test";

	std::cout << "cexpert_register test" << std::endl;
	cexpert_do_unregister(register_test_cstr);
	sleep(1);
	assert(cexpert_is_registered(register_test_cstr) == false);
	std::cout << "\tinitially not registered, ok" << std::endl;
	assert(cexpert_do_register(register_test_cstr));
	std::cout << "\tsucessfully registered" << std::endl;
	sleep(1);
	assert(cexpert_is_registered(register_test_cstr) == true);
	std::cout << "\tsucessfully registered: check ok" << std::endl;
	//TODO check if daemon running
	assert(cexpert_do_unregister(register_test_cstr));
	std::cout << "\tsucessfully unregistered" << std::endl;
	sleep(1);
	assert(cexpert_is_registered(register_test_cstr) == false);
	std::cout << "\tsucessfully unregistered: check ok" << std::endl;
}
